﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;

namespace ThreeByte.ActiveDeck.Service
{
    public class ByteBlockGenerator : IEnumerable
    {
        private readonly int _blockSize;
        private int currentBlock = 0;
        private readonly Stream _stream;
        private readonly byte[] _byteBuffer;

        public ByteBlockGenerator(byte[] data, int blockSize) {
            if(blockSize < 1){
                throw new ArgumentOutOfRangeException("blockSize", "Block Size must be greater than 0");
            }
            BlockList = new BlockList();
            _blockSize = blockSize;
            _byteBuffer = new byte[blockSize];
            _stream = new MemoryStream(data);
            BlockCount = (int)Math.Ceiling((double)data.Length / (double)blockSize);
        }

        public ByteBlockGenerator(Stream stream, int length, int blockSize) {
            if(blockSize < 1) {
                throw new ArgumentOutOfRangeException("blockSize", "Block Size must be greater than 0");
            }
            BlockList = new BlockList();
            _blockSize = blockSize;
            _byteBuffer = new byte[blockSize];
            _stream = stream;
            BlockCount = (int)Math.Ceiling((double)length / (double)blockSize);
        }

        public IEnumerator GetEnumerator() {
            while(HasMoreBlocks()) {
                yield return GetNext();
            }
        }

        public int BlockCount { get; private set; }

        private ByteBlock GetNext() {
            if (!HasMoreBlocks()) {
                throw new InvalidOperationException("No more blocks to return");
            }
            int bytesRead = _stream.Read(_byteBuffer, 0, _blockSize);
            byte[] newBuffer = new byte[bytesRead];
            Array.Copy(_byteBuffer, newBuffer, bytesRead);
            ByteBlock newBlock = new ByteBlock(newBuffer, string.Format("Block {0:00000}", currentBlock++));
            BlockList.Add(newBlock.BlockName);
            return newBlock;
        }

        public BlockList BlockList { get; private set; }

        public bool HasMoreBlocks() {
            return (_stream.Position + 1 < _stream.Length);
        }



    }
}
